﻿using System.Diagnostics;

int linearSearch(int item, int[] arr)
{
    for (int i = 0; i < arr.Length; i++)
        if (arr[i] == item) return i; 
    return -1;
}

int fastLinearSearch(int item, int[] arr)
{
    int[] subArr = new int[arr.Length + 1], one = [item];
    int i = 0;
    
    arr.CopyTo(subArr, 0);
    one.CopyTo(subArr, arr.Length);

    while (true)
    {
        if (subArr[i] == item)
            if (i < arr.Length) return i;
            else return -1;
        i++;
    }
}

int twoFastLinearSearch(int item, int[] arr)
{
    int[] subArr = new int[arr.Length + 1], one = [item];
    int i = 0;
    arr.CopyTo(subArr, 0);
    one.CopyTo(subArr, arr.Length);
    
    q3:
   
    i += 2;
    if (subArr[i] == item) goto q4;
    if (subArr[i + 1] != item) goto q3;
    i++;

    q4:

    if (i < arr.Length + 1) return i;
    else return -1;
}


const string CONSOLE_TEXT = "G - generate new array, F - find value, S - show array, N - exit";
Random rand = new();
int[] nums = null;
Stopwatch sw = new Stopwatch();
TimeSpan ts;
var search = new Dictionary<string, Search> 
{
    { "Linear search", linearSearch },
    { "Fast linear search", fastLinearSearch },
    { "Fast linear search, V2", twoFastLinearSearch }
};
string input = " ";


void genArray(int len)
{
    nums = new int[len];
    for (int i = 0; i < len; i++) nums[i] = rand.Next(10000);
}

void find(int item)
{
    int res;
    string searchName;
    show();

    foreach (var foo in search)
    {
        searchName = foo.Key;
        sw.Start();
        foo.Value(item, nums);
        sw.Stop();
        res = foo.Value(item, nums);

        ts = sw.Elapsed;

        Console.WriteLine("{0, -40}{1}", string.Format(searchName + " ({0:00}:{1:00}:{2:00}:{3:00}): ", ts.Minutes, ts.Seconds, ts.Minutes, ts.Microseconds/10), res);
    }
}

void show()
{
    Console.Write("{0, -40}", "Array: ");
    for (int i = 1; i <= nums.Length; i++)
    {
        Console.Write(nums[i - 1].ToString() + ' ');
        if (i % 10 == 0) Console.Write("\n{0, -40}", "");

    }
    Console.WriteLine();
}

while (input != "N")
{
    Console.Clear();
    Console.WriteLine(CONSOLE_TEXT);
    input = Console.ReadLine().ToUpper();

    switch (input)
    {
        case "G":
            Console.Write("Input length: ");
            int count = Convert.ToInt32(Console.ReadLine());
            if (count > 0)
            {
                genArray(count);
                Console.WriteLine("Cuccess!");
            }
            else Console.WriteLine("length must be more than 0!");
            break;
        case "F":
            if (nums != null)
            {
                Console.Write("Input value: ");
                int value = Convert.ToInt32(Console.ReadLine());
                find(value);
            }
            else Console.WriteLine("Array is empty!");
            break;
        case "S":
            if (nums != null)
            {
                Console.WriteLine();
                show();
                Console.WriteLine();
            }
            else Console.WriteLine("Array is empty!");
            break;
    }

    if (input != "N")
        Console.ReadLine();
}


delegate int Search(int value, int[] mas);